#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <vector>
#include <cstring>
#include <cstdio>
#include "LockGuard.hpp"
using namespace std;
#define NUM 4
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
class Ticket
{
public:
    Ticket(int i, pthread_mutex_t *mutex)
    {
        number_ = "thread-" + to_string(i);
        lock = mutex;
    }

public:
    string number_;
    pthread_mutex_t *lock;
};
int tickets = 3000;
// void *getTickets(void *args)
// {
//     Ticket *ticket = static_cast<Ticket *>(args);
//     while (true)
//     {
//         pthread_mutex_lock(ticket->lock);
//         if (tickets > 0)
//         {
//             usleep(1000);
//             printf("who=%s,get a ticket:%d\n", ticket->number_.c_str(), tickets);
//             tickets--;
//             pthread_mutex_unlock(ticket->lock);
//         }
//         else
//         {
//             pthread_mutex_unlock(ticket->lock);
//             break;
//         }
//         usleep(10);
//     }
//     printf("%s ... quit\n", ticket->number_.c_str());
//     return NULL;
// }

void *getTickets(void *args)
{
    Ticket *ticket = static_cast<Ticket *>(args);
    while (true)
    {
        {
            lock_guard lg(ticket->lock);
            if (tickets > 0)
            {
                usleep(1000);
                printf("who=%s,get a ticket:%d\n", ticket->number_.c_str(), tickets);
                tickets--;
            }
            else
            {
                pthread_cond_wait(&cond, ticket->lock);
            }
        }
        usleep(10);
    }
    // printf("%s ... quit\n", ticket->number_.c_str());
    return NULL;
}
int main()
{
    pthread_mutex_t lock;
    pthread_mutex_init(&lock, NULL);
    vector<pthread_t> tids;
    vector<Ticket *> Ticket_Date;
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        Ticket *ticket = new Ticket(i, &lock);
        Ticket_Date.push_back(ticket);
        pthread_create(&tid, NULL, getTickets, Ticket_Date[i - 1]);
        tids.push_back(tid);
    }
    for (auto thread : tids)
    {
        pthread_join(thread, NULL);
    }
    for (auto i : Ticket_Date)
    {
        delete i;
    }
    pthread_mutex_destroy(&lock);
    return 0;
}